package com.powerflasher.as3potrace
{
   import com.powerflasher.as3potrace.backend.IBackend;
   import com.powerflasher.as3potrace.backend.NullBackend;
   import com.powerflasher.as3potrace.geom.Curve;
   import com.powerflasher.as3potrace.geom.CurveKind;
   import com.powerflasher.as3potrace.geom.Direction;
   import com.powerflasher.as3potrace.geom.MonotonInterval;
   import com.powerflasher.as3potrace.geom.Opti;
   import com.powerflasher.as3potrace.geom.Path;
   import com.powerflasher.as3potrace.geom.PointInt;
   import com.powerflasher.as3potrace.geom.PrivCurve;
   import com.powerflasher.as3potrace.geom.SumStruct;
   import flash.display.BitmapData;
   import flash.geom.Point;
   
   public class POTrace
   {
      
      protected static const POTRACE_CORNER:int = 1;
      
      protected static const POTRACE_CURVETO:int = 2;
      
      protected static const COS179:Number = Math.cos(179 * Math.PI / 180);
       
      
      protected var bmWidth:uint;
      
      protected var bmHeight:uint;
      
      protected var _params:POTraceParams;
      
      protected var _backend:IBackend;
      
      public function POTrace(param1:POTraceParams = null, param2:IBackend = null)
      {
         super();
         this._params = param1 || new POTraceParams();
         this._backend = param2 || new NullBackend();
      }
      
      public function get params() : POTraceParams
      {
         return this._params;
      }
      
      public function set params(param1:POTraceParams) : void
      {
         this._params = param1;
      }
      
      public function get backend() : IBackend
      {
         return this._backend;
      }
      
      public function set backend(param1:IBackend) : void
      {
         this._backend = param1;
      }
      
      public function potrace_trace(param1:BitmapData) : Array
      {
         var _loc3_:int = 0;
         var _loc4_:int = 0;
         var _loc5_:int = 0;
         var _loc11_:Vector.<uint> = null;
         var _loc12_:Array = null;
         var _loc13_:Array = null;
         var _loc14_:Curve = null;
         var _loc2_:BitmapData = new BitmapData(param1.width + 2,param1.height + 2,false,16777215);
         _loc2_.threshold(param1,param1.rect,new Point(1,1),this.params.thresholdOperator,this.params.threshold,0,16777215,false);
         this.bmWidth = _loc2_.width;
         this.bmHeight = _loc2_.height;
         var _loc6_:uint = 0;
         var _loc7_:Vector.<uint> = _loc2_.getVector(_loc2_.rect);
         var _loc8_:Vector.<Vector.<uint>> = new Vector.<Vector.<uint>>(this.bmHeight);
         _loc3_ = 0;
         while(_loc3_ < this.bmHeight)
         {
            _loc11_ = _loc7_.slice(_loc6_,_loc6_ + this.bmWidth);
            _loc4_ = 0;
            while(_loc4_ < _loc11_.length)
            {
               _loc11_[_loc4_] = _loc11_[_loc4_] & 16777215;
               _loc4_++;
            }
            _loc8_[_loc3_] = _loc11_;
            _loc6_ = _loc6_ + this.bmWidth;
            _loc3_++;
         }
         var _loc9_:Array = this.bm_to_pathlist(_loc8_);
         this.process_path(_loc9_);
         var _loc10_:Array = this.pathlist_to_curvearrayslist(_loc9_);
         if(this.backend != null)
         {
            this.backend.init(this.bmWidth,this.bmHeight);
            _loc3_ = 0;
            while(_loc3_ < _loc10_.length)
            {
               this.backend.initShape();
               _loc12_ = _loc10_[_loc3_] as Array;
               _loc4_ = 0;
               while(_loc4_ < _loc12_.length)
               {
                  this.backend.initSubShape(_loc4_ % 2 == 0);
                  _loc13_ = _loc12_[_loc4_] as Array;
                  if(_loc13_.length > 0)
                  {
                     _loc14_ = _loc13_[0] as Curve;
                     this.backend.moveTo(_loc14_.a.clone());
                     _loc5_ = 0;
                     while(_loc5_ < _loc13_.length)
                     {
                        _loc14_ = _loc13_[_loc5_] as Curve;
                        switch(_loc14_.kind)
                        {
                           case CurveKind.BEZIER:
                              this.backend.addBezier(_loc14_.a.clone(),_loc14_.cpa.clone(),_loc14_.cpb.clone(),_loc14_.b.clone());
                              break;
                           case CurveKind.LINE:
                              this.backend.addLine(_loc14_.a.clone(),_loc14_.b.clone());
                        }
                        _loc5_++;
                     }
                  }
                  this.backend.exitSubShape();
                  _loc4_++;
               }
               this.backend.exitShape();
               _loc3_++;
            }
            this.backend.exit();
         }
         return _loc10_;
      }
      
      private function bm_to_pathlist(param1:Vector.<Vector.<uint>>) : Array
      {
         var _loc3_:PointInt = null;
         var _loc2_:Array = [];
         while((_loc3_ = this.find_next(param1)) != null)
         {
            this.get_contour(param1,_loc3_,_loc2_);
         }
         return _loc2_;
      }
      
      private function find_next(param1:Vector.<Vector.<uint>>) : PointInt
      {
         var _loc2_:int = 0;
         var _loc3_:int = 0;
         _loc3_ = 1;
         while(_loc3_ < this.bmHeight - 1)
         {
            _loc2_ = 0;
            while(_loc2_ < this.bmWidth - 1)
            {
               if(param1[_loc3_][_loc2_ + 1] == 0)
               {
                  return new PointInt(_loc2_,_loc3_);
               }
               _loc2_++;
            }
            _loc3_++;
         }
         return null;
      }
      
      private function get_contour(param1:Vector.<Vector.<uint>>, param2:PointInt, param3:Array) : void
      {
         var _loc6_:Path = null;
         var _loc4_:Array = [];
         var _loc5_:Path = this.find_path(param1,param2);
         this.xor_path(param1,_loc5_);
         if(_loc5_.area > this.params.turdSize)
         {
            _loc4_.push(_loc5_);
            param3.push(_loc4_);
         }
         while((param2 = this.find_next_in_path(param1,_loc5_)) != null)
         {
            _loc6_ = this.find_path(param1,param2);
            this.xor_path(param1,_loc6_);
            if(_loc6_.area > this.params.turdSize)
            {
               _loc4_.push(_loc6_);
            }
            if((param2 = this.find_next_in_path(param1,_loc6_)) != null)
            {
               this.get_contour(param1,param2,param3);
            }
         }
      }
      
      private function find_path(param1:Vector.<Vector.<uint>>, param2:PointInt) : Path
      {
         var _loc9_:int = 0;
         var _loc3_:Vector.<PointInt> = new Vector.<PointInt>();
         var _loc4_:PointInt = param2.clone();
         var _loc5_:uint = Direction.NORTH;
         var _loc6_:int = 0;
         do
         {
            _loc3_.push(_loc4_.clone());
            _loc9_ = _loc4_.y;
            _loc5_ = this.find_next_trace(param1,_loc4_,_loc5_);
            _loc6_ = _loc6_ + _loc4_.x * (_loc9_ - _loc4_.y);
         }
         while(_loc4_.x != param2.x || _loc4_.y != param2.y);
         
         if(_loc3_.length == 0)
         {
            return null;
         }
         var _loc7_:Path = new Path();
         _loc7_.area = _loc6_;
         _loc7_.pt = new Vector.<PointInt>(_loc3_.length);
         var _loc8_:int = 0;
         while(_loc8_ < _loc3_.length)
         {
            _loc7_.pt[_loc8_] = _loc3_[_loc8_];
            _loc8_++;
         }
         if(_loc7_.pt.length > 1)
         {
            _loc7_.pt.unshift(_loc7_.pt.pop());
         }
         _loc7_.monotonIntervals = this.get_monoton_intervals(_loc7_.pt);
         return _loc7_;
      }
      
      private function find_next_in_path(param1:Vector.<Vector.<uint>>, param2:Path) : PointInt
      {
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         var _loc11_:int = 0;
         var _loc12_:int = 0;
         var _loc13_:int = 0;
         var _loc14_:MonotonInterval = null;
         var _loc15_:int = 0;
         var _loc16_:MonotonInterval = null;
         var _loc17_:int = 0;
         if(param2.monotonIntervals.length == 0)
         {
            return null;
         }
         var _loc3_:int = 0;
         var _loc4_:int = param2.pt.length;
         var _loc5_:Vector.<MonotonInterval> = param2.monotonIntervals;
         var _loc6_:MonotonInterval = _loc5_[0];
         _loc6_.resetCurrentId(_loc4_);
         var _loc7_:int = param2.pt[_loc6_.currentId].y;
         var _loc8_:Vector.<MonotonInterval> = new Vector.<MonotonInterval>();
         _loc8_[0] = _loc6_;
         _loc6_.currentId = _loc6_.min();
         while(_loc5_.length > _loc3_ + 1 && _loc5_[_loc3_ + 1].minY(param2.pt) == _loc7_)
         {
            _loc6_ = _loc5_[_loc3_ + 1];
            _loc6_.resetCurrentId(_loc4_);
            _loc8_.push(_loc6_);
            _loc3_++;
         }
         while(_loc8_.length > 0)
         {
            _loc10_ = 0;
            while(_loc10_ < _loc8_.length - 1)
            {
               _loc11_ = param2.pt[_loc8_[_loc10_].currentId].x + 1;
               _loc12_ = param2.pt[_loc8_[_loc10_ + 1].currentId].x;
               _loc13_ = _loc11_;
               while(_loc13_ <= _loc12_)
               {
                  if(param1[_loc7_][_loc13_] == 0)
                  {
                     return new PointInt(_loc13_ - 1,_loc7_);
                  }
                  _loc13_++;
               }
               _loc10_++;
               _loc10_++;
            }
            _loc7_++;
            _loc9_ = _loc8_.length - 1;
            while(_loc9_ >= 0)
            {
               _loc14_ = _loc8_[_loc9_];
               if(_loc7_ > _loc14_.maxY(param2.pt))
               {
                  _loc8_.splice(_loc9_,1);
               }
               else
               {
                  _loc15_ = _loc14_.currentId;
                  do
                  {
                     _loc15_ = !!_loc14_.increasing?int(this.mod(_loc15_ + 1,_loc4_)):int(this.mod(_loc15_ - 1,_loc4_));
                  }
                  while(param2.pt[_loc15_].y < _loc7_);
                  
                  _loc14_.currentId = _loc15_;
               }
               _loc9_--;
            }
            while(_loc5_.length > _loc3_ + 1 && _loc5_[_loc3_ + 1].minY(param2.pt) == _loc7_)
            {
               _loc16_ = _loc5_[_loc3_ + 1];
               _loc9_ = 0;
               _loc17_ = param2.pt[_loc16_.min()].x;
               while(_loc8_.length > _loc9_ && _loc17_ > param2.pt[_loc8_[_loc9_].currentId].x)
               {
                  _loc9_++;
               }
               _loc8_.splice(_loc9_,0,_loc16_);
               _loc16_.resetCurrentId(_loc4_);
               _loc3_++;
            }
         }
         return null;
      }
      
      private function xor_path(param1:Vector.<Vector.<uint>>, param2:Path) : void
      {
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         var _loc11_:int = 0;
         var _loc12_:int = 0;
         var _loc13_:int = 0;
         var _loc14_:MonotonInterval = null;
         var _loc15_:int = 0;
         var _loc16_:MonotonInterval = null;
         var _loc17_:int = 0;
         if(param2.monotonIntervals.length == 0)
         {
            return;
         }
         var _loc3_:int = 0;
         var _loc4_:int = param2.pt.length;
         var _loc5_:Vector.<MonotonInterval> = param2.monotonIntervals;
         var _loc6_:MonotonInterval = _loc5_[0];
         _loc6_.resetCurrentId(_loc4_);
         var _loc7_:int = param2.pt[_loc6_.currentId].y;
         var _loc8_:Vector.<MonotonInterval> = new Vector.<MonotonInterval>();
         _loc8_.push(_loc6_);
         _loc6_.currentId = _loc6_.min();
         while(_loc5_.length > _loc3_ + 1 && _loc5_[_loc3_ + 1].minY(param2.pt) == _loc7_)
         {
            _loc6_ = _loc5_[_loc3_ + 1];
            _loc6_.resetCurrentId(_loc4_);
            _loc8_.push(_loc6_);
            _loc3_++;
         }
         while(_loc8_.length > 0)
         {
            _loc10_ = 0;
            while(_loc10_ < _loc8_.length - 1)
            {
               _loc11_ = param2.pt[_loc8_[_loc10_].currentId].x + 1;
               _loc12_ = param2.pt[_loc8_[_loc10_ + 1].currentId].x;
               _loc13_ = _loc11_;
               while(_loc13_ <= _loc12_)
               {
                  param1[_loc7_][_loc13_] = param1[_loc7_][_loc13_] ^ 16777215;
                  _loc13_++;
               }
               _loc10_++;
               _loc10_++;
            }
            _loc7_++;
            _loc9_ = _loc8_.length - 1;
            while(_loc9_ >= 0)
            {
               _loc14_ = _loc8_[_loc9_];
               if(_loc7_ > _loc14_.maxY(param2.pt))
               {
                  _loc8_.splice(_loc9_,1);
               }
               else
               {
                  _loc15_ = _loc14_.currentId;
                  do
                  {
                     _loc15_ = !!_loc14_.increasing?int(this.mod(_loc15_ + 1,_loc4_)):int(this.mod(_loc15_ - 1,_loc4_));
                  }
                  while(param2.pt[_loc15_].y < _loc7_);
                  
                  _loc14_.currentId = _loc15_;
               }
               _loc9_--;
            }
            while(_loc5_.length > _loc3_ + 1 && _loc5_[_loc3_ + 1].minY(param2.pt) == _loc7_)
            {
               _loc16_ = _loc5_[_loc3_ + 1];
               _loc9_ = 0;
               _loc17_ = param2.pt[_loc16_.min()].x;
               while(_loc8_.length > _loc9_ && _loc17_ > param2.pt[_loc8_[_loc9_].currentId].x)
               {
                  _loc9_++;
               }
               _loc8_.splice(_loc9_,0,_loc16_);
               _loc16_.resetCurrentId(_loc4_);
               _loc3_++;
            }
         }
      }
      
      private function get_monoton_intervals(param1:Vector.<PointInt>) : Vector.<MonotonInterval>
      {
         var _loc9_:int = 0;
         var _loc10_:MonotonInterval = null;
         var _loc11_:MonotonInterval = null;
         var _loc2_:Vector.<MonotonInterval> = new Vector.<MonotonInterval>();
         var _loc3_:uint = param1.length;
         if(_loc3_ == 0)
         {
            return _loc2_;
         }
         var _loc4_:Vector.<MonotonInterval> = new Vector.<MonotonInterval>();
         var _loc5_:int = 0;
         while(param1[_loc5_].y == param1[_loc5_ + 1].y)
         {
            _loc5_++;
         }
         var _loc6_:int = _loc5_;
         var _loc7_:* = param1[_loc5_].y < param1[_loc5_ + 1].y;
         var _loc8_:MonotonInterval = new MonotonInterval(_loc7_,_loc5_,_loc5_);
         _loc4_.push(_loc8_);
         do
         {
            _loc9_ = this.mod(_loc6_ + 1,_loc3_);
            if(param1[_loc6_].y == param1[_loc9_].y || _loc7_ == param1[_loc6_].y < param1[_loc9_].y)
            {
               _loc8_.to = _loc6_;
            }
            else
            {
               _loc7_ = param1[_loc6_].y < param1[_loc9_].y;
               _loc8_ = new MonotonInterval(_loc7_,_loc6_,_loc6_);
               _loc4_.push(_loc8_);
            }
            _loc6_ = _loc9_;
         }
         while(_loc6_ != _loc5_);
         
         if((_loc4_.length & 1) == 1)
         {
            _loc10_ = _loc4_.pop();
            _loc4_[0].from = _loc10_.from;
         }
         while(_loc4_.length > 0)
         {
            _loc6_ = 0;
            _loc11_ = _loc4_.shift();
            while(_loc6_ < _loc2_.length && param1[_loc11_.min()].y > param1[_loc2_[_loc6_].min()].y)
            {
               _loc6_++;
            }
            while(_loc6_ < _loc2_.length && param1[_loc11_.min()].y == param1[_loc2_[_loc6_].min()].y && param1[_loc11_.min()].x > param1[_loc2_[_loc6_].min()].x)
            {
               _loc6_++;
            }
            _loc2_.splice(_loc6_,0,_loc11_);
         }
         return _loc2_;
      }
      
      private function find_next_trace(param1:Vector.<Vector.<uint>>, param2:PointInt, param3:uint) : uint
      {
         switch(param3)
         {
            case Direction.WEST:
               if(param1[param2.y + 1][param2.x + 1] == 0)
               {
                  param3 = Direction.NORTH;
                  param2.y++;
               }
               else if(param1[param2.y][param2.x + 1] == 0)
               {
                  param3 = Direction.WEST;
                  param2.x++;
               }
               else
               {
                  param3 = Direction.SOUTH;
                  param2.y--;
               }
               break;
            case Direction.SOUTH:
               if(param1[param2.y][param2.x + 1] == 0)
               {
                  param3 = Direction.WEST;
                  param2.x++;
               }
               else if(param1[param2.y][param2.x] == 0)
               {
                  param3 = Direction.SOUTH;
                  param2.y--;
               }
               else
               {
                  param3 = Direction.EAST;
                  param2.x--;
               }
               break;
            case Direction.EAST:
               if(param1[param2.y][param2.x] == 0)
               {
                  param3 = Direction.SOUTH;
                  param2.y--;
               }
               else if(param1[param2.y + 1][param2.x] == 0)
               {
                  param3 = Direction.EAST;
                  param2.x--;
               }
               else
               {
                  param3 = Direction.NORTH;
                  param2.y++;
               }
               break;
            case Direction.NORTH:
               if(param1[param2.y + 1][param2.x] == 0)
               {
                  param3 = Direction.EAST;
                  param2.x--;
               }
               else if(param1[param2.y + 1][param2.x + 1] == 0)
               {
                  param3 = Direction.NORTH;
                  param2.y++;
               }
               else
               {
                  param3 = Direction.WEST;
                  param2.x++;
               }
         }
         return param3;
      }
      
      private function process_path(param1:Array) : void
      {
         var _loc3_:Array = null;
         var _loc4_:int = 0;
         var _loc5_:Path = null;
         var _loc2_:int = 0;
         while(_loc2_ < param1.length)
         {
            _loc3_ = param1[_loc2_] as Array;
            _loc4_ = 0;
            while(_loc4_ < _loc3_.length)
            {
               _loc5_ = _loc3_[_loc4_] as Path;
               this.calc_sums(_loc5_);
               this.calc_lon(_loc5_);
               this.bestpolygon(_loc5_);
               this.adjust_vertices(_loc5_);
               this.smooth(_loc5_.curves,1,this.params.alphaMax);
               if(this.params.curveOptimizing)
               {
                  this.opticurve(_loc5_,this.params.optTolerance);
                  _loc5_.fCurves = _loc5_.optimizedCurves;
               }
               else
               {
                  _loc5_.fCurves = _loc5_.curves;
               }
               _loc5_.curves = _loc5_.fCurves;
               _loc4_++;
            }
            _loc2_++;
         }
      }
      
      private function calc_sums(param1:Path) : void
      {
         var _loc7_:int = 0;
         var _loc8_:int = 0;
         var _loc2_:int = param1.pt.length;
         var _loc3_:int = param1.pt[0].x;
         var _loc4_:int = param1.pt[0].y;
         param1.sums = new Vector.<SumStruct>(_loc2_ + 1);
         var _loc5_:SumStruct = new SumStruct();
         _loc5_.x2 = _loc5_.xy = _loc5_.y2 = _loc5_.x = _loc5_.y = 0;
         param1.sums[0] = _loc5_;
         var _loc6_:int = 0;
         while(_loc6_ < _loc2_)
         {
            _loc7_ = param1.pt[_loc6_].x - _loc3_;
            _loc8_ = param1.pt[_loc6_].y - _loc4_;
            _loc5_ = new SumStruct();
            _loc5_.x = param1.sums[_loc6_].x + _loc7_;
            _loc5_.y = param1.sums[_loc6_].y + _loc8_;
            _loc5_.x2 = param1.sums[_loc6_].x2 + _loc7_ * _loc7_;
            _loc5_.xy = param1.sums[_loc6_].xy + _loc7_ * _loc8_;
            _loc5_.y2 = param1.sums[_loc6_].y2 + _loc8_ * _loc8_;
            param1.sums[_loc6_ + 1] = _loc5_;
            _loc6_++;
         }
      }
      
      private function calc_lon(param1:Path) : void
      {
         var _loc2_:int = 0;
         var _loc3_:int = 0;
         var _loc4_:int = 0;
         var _loc5_:int = 0;
         var _loc6_:int = 0;
         var _loc7_:int = 0;
         var _loc8_:int = 0;
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         var _loc20_:Boolean = false;
         var _loc11_:Vector.<int> = new Vector.<int>(4);
         var _loc12_:Vector.<PointInt> = new Vector.<PointInt>(2);
         _loc12_[0] = new PointInt();
         _loc12_[1] = new PointInt();
         var _loc13_:PointInt = new PointInt();
         var _loc14_:PointInt = new PointInt();
         var _loc15_:PointInt = new PointInt();
         var _loc16_:Vector.<PointInt> = param1.pt;
         var _loc17_:int = _loc16_.length;
         var _loc18_:Vector.<int> = new Vector.<int>(_loc17_);
         var _loc19_:Vector.<int> = new Vector.<int>(_loc17_);
         _loc4_ = 0;
         _loc2_ = _loc17_ - 1;
         while(_loc2_ >= 0)
         {
            if(_loc16_[_loc2_].x != _loc16_[_loc4_].x && _loc16_[_loc2_].y != _loc16_[_loc4_].y)
            {
               _loc4_ = _loc2_ + 1;
            }
            _loc19_[_loc2_] = _loc4_;
            _loc2_--;
         }
         param1.lon = new Vector.<int>(_loc17_);
         _loc2_ = _loc17_ - 1;
         while(_loc2_ >= 0)
         {
            _loc11_[0] = _loc11_[1] = _loc11_[2] = _loc11_[3] = 0;
            _loc10_ = (3 + 3 * (_loc16_[this.mod(_loc2_ + 1,_loc17_)].x - _loc16_[_loc2_].x) + (_loc16_[this.mod(_loc2_ + 1,_loc17_)].y - _loc16_[_loc2_].y)) / 2;
            _loc11_[_loc10_ % 4]++;
            _loc12_[0].x = 0;
            _loc12_[0].y = 0;
            _loc12_[1].x = 0;
            _loc12_[1].y = 0;
            _loc4_ = _loc19_[_loc2_];
            _loc5_ = _loc2_;
            _loc20_ = false;
            do
            {
               _loc10_ = (3 + 3 * this.sign(_loc16_[_loc4_].x - _loc16_[_loc5_].x) + this.sign(_loc16_[_loc4_].y - _loc16_[_loc5_].y)) / 2;
               _loc11_[_loc10_]++;
               if(_loc11_[0] >= 1 && _loc11_[1] >= 1 && _loc11_[2] >= 1 && _loc11_[3] >= 1)
               {
                  _loc18_[_loc2_] = _loc5_;
                  _loc20_ = true;
                  break;
               }
               _loc13_.x = _loc16_[_loc4_].x - _loc16_[_loc2_].x;
               _loc13_.y = _loc16_[_loc4_].y - _loc16_[_loc2_].y;
               if(this.xprod(_loc12_[0],_loc13_) < 0 || this.xprod(_loc12_[1],_loc13_) > 0)
               {
                  break;
               }
               if(!(this.abs(_loc13_.x) <= 1 && this.abs(_loc13_.y) <= 1))
               {
                  _loc14_.x = _loc13_.x + (_loc13_.y >= 0 && (_loc13_.y > 0 || _loc13_.x < 0)?1:-1);
                  _loc14_.y = _loc13_.y + (_loc13_.x <= 0 && (_loc13_.x < 0 || _loc13_.y < 0)?1:-1);
                  if(this.xprod(_loc12_[0],_loc14_) >= 0)
                  {
                     _loc12_[0] = _loc14_.clone();
                  }
                  _loc14_.x = _loc13_.x + (_loc13_.y <= 0 && (_loc13_.y < 0 || _loc13_.x < 0)?1:-1);
                  _loc14_.y = _loc13_.y + (_loc13_.x >= 0 && (_loc13_.x > 0 || _loc13_.y < 0)?1:-1);
                  if(this.xprod(_loc12_[1],_loc14_) <= 0)
                  {
                     _loc12_[1] = _loc14_.clone();
                  }
               }
               _loc5_ = _loc4_;
               _loc4_ = _loc19_[_loc5_];
            }
            while(this.cyclic(_loc4_,_loc2_,_loc5_));
            
            if(!_loc20_)
            {
               _loc15_.x = this.sign(_loc16_[_loc4_].x - _loc16_[_loc5_].x);
               _loc15_.y = this.sign(_loc16_[_loc4_].y - _loc16_[_loc5_].y);
               _loc13_.x = _loc16_[_loc5_].x - _loc16_[_loc2_].x;
               _loc13_.y = _loc16_[_loc5_].y - _loc16_[_loc2_].y;
               _loc6_ = this.xprod(_loc12_[0],_loc13_);
               _loc7_ = this.xprod(_loc12_[0],_loc15_);
               _loc8_ = this.xprod(_loc12_[1],_loc13_);
               _loc9_ = this.xprod(_loc12_[1],_loc15_);
               _loc3_ = int.MAX_VALUE;
               if(_loc7_ < 0)
               {
                  _loc3_ = this.floordiv(_loc6_,-_loc7_);
               }
               if(_loc9_ > 0)
               {
                  _loc3_ = this.min(_loc3_,this.floordiv(-_loc8_,_loc9_));
               }
               _loc18_[_loc2_] = this.mod(_loc5_ + _loc3_,_loc17_);
            }
            _loc2_--;
         }
         _loc3_ = _loc18_[_loc17_ - 1];
         param1.lon[_loc17_ - 1] = _loc3_;
         _loc2_ = _loc17_ - 2;
         while(_loc2_ >= 0)
         {
            if(this.cyclic(_loc2_ + 1,_loc18_[_loc2_],_loc3_))
            {
               _loc3_ = _loc18_[_loc2_];
            }
            param1.lon[_loc2_] = _loc3_;
            _loc2_--;
         }
         _loc2_ = _loc17_ - 1;
         while(this.cyclic(this.mod(_loc2_ + 1,_loc17_),_loc3_,param1.lon[_loc2_]))
         {
            param1.lon[_loc2_] = _loc3_;
            _loc2_--;
         }
      }
      
      private function penalty3(param1:Path, param2:int, param3:int) : Number
      {
         var _loc4_:int = param1.pt.length;
         var _loc5_:Vector.<SumStruct> = param1.sums;
         var _loc6_:Vector.<PointInt> = param1.pt;
         var _loc7_:int = 0;
         if(param3 >= _loc4_)
         {
            param3 = param3 - _loc4_;
            _loc7_++;
         }
         var _loc8_:Number = _loc5_[param3 + 1].x - _loc5_[param2].x + _loc7_ * _loc5_[_loc4_].x;
         var _loc9_:Number = _loc5_[param3 + 1].y - _loc5_[param2].y + _loc7_ * _loc5_[_loc4_].y;
         var _loc10_:Number = _loc5_[param3 + 1].x2 - _loc5_[param2].x2 + _loc7_ * _loc5_[_loc4_].x2;
         var _loc11_:Number = _loc5_[param3 + 1].xy - _loc5_[param2].xy + _loc7_ * _loc5_[_loc4_].xy;
         var _loc12_:Number = _loc5_[param3 + 1].y2 - _loc5_[param2].y2 + _loc7_ * _loc5_[_loc4_].y2;
         var _loc13_:Number = param3 + 1 - param2 + _loc7_ * _loc4_;
         var _loc14_:Number = (_loc6_[param2].x + _loc6_[param3].x) / 2 - _loc6_[0].x;
         var _loc15_:Number = (_loc6_[param2].y + _loc6_[param3].y) / 2 - _loc6_[0].y;
         var _loc16_:Number = _loc6_[param3].x - _loc6_[param2].x;
         var _loc17_:Number = -(_loc6_[param3].y - _loc6_[param2].y);
         var _loc18_:Number = (_loc10_ - 2 * _loc8_ * _loc14_) / _loc13_ + _loc14_ * _loc14_;
         var _loc19_:Number = (_loc11_ - _loc8_ * _loc15_ - _loc9_ * _loc14_) / _loc13_ + _loc14_ * _loc15_;
         var _loc20_:Number = (_loc12_ - 2 * _loc9_ * _loc15_) / _loc13_ + _loc15_ * _loc15_;
         return Math.sqrt(_loc17_ * _loc17_ * _loc18_ + 2 * _loc17_ * _loc16_ * _loc19_ + _loc16_ * _loc16_ * _loc20_);
      }
      
      private function bestpolygon(param1:Path) : void
      {
         var _loc2_:int = 0;
         var _loc3_:int = 0;
         var _loc4_:int = 0;
         var _loc5_:int = 0;
         var _loc13_:Number = NaN;
         var _loc14_:Number = NaN;
         var _loc15_:int = 0;
         var _loc6_:int = param1.pt.length;
         var _loc7_:Vector.<Number> = new Vector.<Number>(_loc6_ + 1);
         var _loc8_:Vector.<int> = new Vector.<int>(_loc6_ + 1);
         var _loc9_:Vector.<int> = new Vector.<int>(_loc6_);
         var _loc10_:Vector.<int> = new Vector.<int>(_loc6_ + 1);
         var _loc11_:Vector.<int> = new Vector.<int>(_loc6_ + 1);
         var _loc12_:Vector.<int> = new Vector.<int>(_loc6_ + 1);
         _loc2_ = 0;
         while(_loc2_ < _loc6_)
         {
            _loc15_ = this.mod(param1.lon[this.mod(_loc2_ - 1,_loc6_)] - 1,_loc6_);
            if(_loc15_ == _loc2_)
            {
               _loc15_ = this.mod(_loc2_ + 1,_loc6_);
            }
            _loc9_[_loc2_] = _loc15_ < _loc2_?int(_loc6_):int(_loc15_);
            _loc2_++;
         }
         _loc3_ = 1;
         _loc2_ = 0;
         while(_loc2_ < _loc6_)
         {
            while(_loc3_ <= _loc9_[_loc2_])
            {
               _loc10_[_loc3_] = _loc2_;
               _loc3_++;
            }
            _loc2_++;
         }
         _loc2_ = 0;
         _loc3_ = 0;
         while(_loc2_ < _loc6_)
         {
            _loc11_[_loc3_] = _loc2_;
            _loc2_ = _loc9_[_loc2_];
            _loc3_++;
         }
         _loc11_[_loc3_] = _loc6_;
         _loc2_ = _loc6_;
         _loc4_ = _loc3_;
         _loc3_ = _loc4_;
         while(_loc3_ > 0)
         {
            _loc12_[_loc3_] = _loc2_;
            _loc2_ = _loc10_[_loc2_];
            _loc3_--;
         }
         _loc12_[0] = 0;
         _loc7_[0] = 0;
         _loc3_ = 1;
         while(_loc3_ <= _loc4_)
         {
            _loc2_ = _loc12_[_loc3_];
            while(_loc2_ <= _loc11_[_loc3_])
            {
               _loc14_ = -1;
               _loc5_ = _loc11_[_loc3_ - 1];
               while(_loc5_ >= _loc10_[_loc2_])
               {
                  _loc13_ = this.penalty3(param1,_loc5_,_loc2_) + _loc7_[_loc5_];
                  if(_loc14_ < 0 || _loc13_ < _loc14_)
                  {
                     _loc8_[_loc2_] = _loc5_;
                     _loc14_ = _loc13_;
                  }
                  _loc5_--;
               }
               _loc7_[_loc2_] = _loc14_;
               _loc2_++;
            }
            _loc3_++;
         }
         param1.po = new Vector.<int>(_loc4_);
         _loc2_ = _loc6_;
         _loc3_ = _loc4_ - 1;
         while(_loc2_ > 0)
         {
            _loc2_ = _loc8_[_loc2_];
            param1.po[_loc3_] = _loc2_;
            _loc3_--;
         }
      }
      
      private function adjust_vertices(param1:Path) : void
      {
         var _loc8_:int = 0;
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         var _loc11_:int = 0;
         var _loc12_:Number = NaN;
         var _loc18_:Vector.<Vector.<Number>> = null;
         var _loc19_:Point = null;
         var _loc20_:Number = NaN;
         var _loc21_:Number = NaN;
         var _loc22_:Number = NaN;
         var _loc23_:Number = NaN;
         var _loc24_:Number = NaN;
         var _loc25_:Number = NaN;
         var _loc26_:Number = NaN;
         var _loc27_:int = 0;
         var _loc2_:Vector.<PointInt> = param1.pt;
         var _loc3_:Vector.<int> = param1.po;
         var _loc4_:int = _loc2_.length;
         var _loc5_:int = _loc3_.length;
         var _loc6_:int = _loc2_[0].x;
         var _loc7_:int = _loc2_[0].y;
         var _loc13_:Vector.<Number> = new Vector.<Number>(3);
         var _loc14_:Vector.<Vector.<Vector.<Number>>> = new Vector.<Vector.<Vector.<Number>>>(_loc5_);
         var _loc15_:Vector.<Point> = new Vector.<Point>(_loc5_);
         var _loc16_:Vector.<Point> = new Vector.<Point>(_loc5_);
         _loc8_ = 0;
         while(_loc8_ < _loc5_)
         {
            _loc14_[_loc8_] = new Vector.<Vector.<Number>>(3);
            _loc9_ = 0;
            while(_loc9_ < 3)
            {
               _loc14_[_loc8_][_loc9_] = new Vector.<Number>(3);
               _loc9_++;
            }
            _loc15_[_loc8_] = new Point();
            _loc16_[_loc8_] = new Point();
            _loc8_++;
         }
         var _loc17_:Point = new Point();
         param1.curves = new PrivCurve(_loc5_);
         _loc8_ = 0;
         while(_loc8_ < _loc5_)
         {
            _loc9_ = _loc3_[this.mod(_loc8_ + 1,_loc5_)];
            _loc9_ = this.mod(_loc9_ - _loc3_[_loc8_],_loc4_) + _loc3_[_loc8_];
            this.pointslope(param1,_loc3_[_loc8_],_loc9_,_loc15_[_loc8_],_loc16_[_loc8_]);
            _loc8_++;
         }
         _loc8_ = 0;
         while(_loc8_ < _loc5_)
         {
            _loc12_ = _loc16_[_loc8_].x * _loc16_[_loc8_].x + _loc16_[_loc8_].y * _loc16_[_loc8_].y;
            if(_loc12_ == 0)
            {
               _loc9_ = 0;
               while(_loc9_ < 3)
               {
                  _loc10_ = 0;
                  while(_loc10_ < 3)
                  {
                     _loc14_[_loc8_][_loc9_][_loc10_] = 0;
                     _loc10_++;
                  }
                  _loc9_++;
               }
            }
            else
            {
               _loc13_[0] = _loc16_[_loc8_].y;
               _loc13_[1] = -_loc16_[_loc8_].x;
               _loc13_[2] = -_loc13_[1] * _loc15_[_loc8_].y - _loc13_[0] * _loc15_[_loc8_].x;
               _loc11_ = 0;
               while(_loc11_ < 3)
               {
                  _loc10_ = 0;
                  while(_loc10_ < 3)
                  {
                     _loc14_[_loc8_][_loc11_][_loc10_] = _loc13_[_loc11_] * _loc13_[_loc10_] / _loc12_;
                     _loc10_++;
                  }
                  _loc11_++;
               }
            }
            _loc8_++;
         }
         _loc8_ = 0;
         while(_loc8_ < _loc5_)
         {
            _loc18_ = new Vector.<Vector.<Number>>(3);
            _loc19_ = new Point();
            _loc9_ = 0;
            while(_loc9_ < 3)
            {
               _loc18_[_loc9_] = new Vector.<Number>(3);
               _loc9_++;
            }
            _loc17_.x = _loc2_[_loc3_[_loc8_]].x - _loc6_;
            _loc17_.y = _loc2_[_loc3_[_loc8_]].y - _loc7_;
            _loc9_ = this.mod(_loc8_ - 1,_loc5_);
            _loc11_ = 0;
            while(_loc11_ < 3)
            {
               _loc10_ = 0;
               while(_loc10_ < 3)
               {
                  _loc18_[_loc11_][_loc10_] = _loc14_[_loc9_][_loc11_][_loc10_] + _loc14_[_loc8_][_loc11_][_loc10_];
                  _loc10_++;
               }
               _loc11_++;
            }
            while(true)
            {
               _loc22_ = _loc18_[0][0] * _loc18_[1][1] - _loc18_[0][1] * _loc18_[1][0];
               if(_loc22_ != 0)
               {
                  break;
               }
               if(_loc18_[0][0] > _loc18_[1][1])
               {
                  _loc13_[0] = -_loc18_[0][1];
                  _loc13_[1] = _loc18_[0][0];
               }
               else if(_loc18_[1][1] != 0)
               {
                  _loc13_[0] = -_loc18_[1][1];
                  _loc13_[1] = _loc18_[1][0];
               }
               else
               {
                  _loc13_[0] = 1;
                  _loc13_[1] = 0;
               }
               _loc12_ = _loc13_[0] * _loc13_[0] + _loc13_[1] * _loc13_[1];
               _loc13_[2] = -_loc13_[1] * _loc17_.y - _loc13_[0] * _loc17_.x;
               _loc11_ = 0;
               while(_loc11_ < 3)
               {
                  _loc10_ = 0;
                  while(_loc10_ < 3)
                  {
                     _loc18_[_loc11_][_loc10_] = _loc18_[_loc11_][_loc10_] + _loc13_[_loc11_] * _loc13_[_loc10_] / _loc12_;
                     _loc10_++;
                  }
                  _loc11_++;
               }
            }
            _loc19_.x = (-_loc18_[0][2] * _loc18_[1][1] + _loc18_[1][2] * _loc18_[0][1]) / _loc22_;
            _loc19_.y = (_loc18_[0][2] * _loc18_[1][0] - _loc18_[1][2] * _loc18_[0][0]) / _loc22_;
            _loc20_ = Math.abs(_loc19_.x - _loc17_.x);
            _loc21_ = Math.abs(_loc19_.y - _loc17_.y);
            if(_loc20_ <= 0.5 && _loc21_ <= 0.5)
            {
               param1.curves.vertex[_loc8_] = new Point(_loc19_.x + _loc6_,_loc19_.y + _loc7_);
            }
            else
            {
               _loc23_ = this.quadform(_loc18_,_loc17_);
               _loc25_ = _loc17_.x;
               _loc26_ = _loc17_.y;
               if(_loc18_[0][0] != 0)
               {
                  _loc27_ = 0;
                  while(_loc27_ < 2)
                  {
                     _loc19_.y = _loc17_.y - 0.5 + _loc27_;
                     _loc19_.x = -(_loc18_[0][1] * _loc19_.y + _loc18_[0][2]) / _loc18_[0][0];
                     _loc20_ = Math.abs(_loc19_.x - _loc17_.x);
                     _loc24_ = this.quadform(_loc18_,_loc19_);
                     if(_loc20_ <= 0.5 && _loc24_ < _loc23_)
                     {
                        _loc23_ = _loc24_;
                        _loc25_ = _loc19_.x;
                        _loc26_ = _loc19_.y;
                     }
                     _loc27_++;
                  }
               }
               if(_loc18_[1][1] != 0)
               {
                  _loc27_ = 0;
                  while(_loc27_ < 2)
                  {
                     _loc19_.x = _loc17_.x - 0.5 + _loc27_;
                     _loc19_.y = -(_loc18_[1][0] * _loc19_.x + _loc18_[1][2]) / _loc18_[1][1];
                     _loc21_ = Math.abs(_loc19_.y - _loc17_.y);
                     _loc24_ = this.quadform(_loc18_,_loc19_);
                     if(_loc21_ <= 0.5 && _loc24_ < _loc23_)
                     {
                        _loc23_ = _loc24_;
                        _loc25_ = _loc19_.x;
                        _loc26_ = _loc19_.y;
                     }
                     _loc27_++;
                  }
               }
               _loc11_ = 0;
               while(_loc11_ < 2)
               {
                  _loc10_ = 0;
                  while(_loc10_ < 2)
                  {
                     _loc19_.x = _loc17_.x - 0.5 + _loc11_;
                     _loc19_.y = _loc17_.y - 0.5 + _loc10_;
                     _loc24_ = this.quadform(_loc18_,_loc19_);
                     if(_loc24_ < _loc23_)
                     {
                        _loc23_ = _loc24_;
                        _loc25_ = _loc19_.x;
                        _loc26_ = _loc19_.y;
                     }
                     _loc10_++;
                  }
                  _loc11_++;
               }
               param1.curves.vertex[_loc8_] = new Point(_loc25_ + _loc6_ - 1,_loc26_ + _loc7_ - 1);
            }
            _loc8_++;
         }
      }
      
      private function smooth(param1:PrivCurve, param2:int, param3:Number) : void
      {
         var _loc5_:int = 0;
         var _loc6_:int = 0;
         var _loc7_:int = 0;
         var _loc8_:Number = NaN;
         var _loc9_:Number = NaN;
         var _loc10_:Number = NaN;
         var _loc11_:Point = null;
         var _loc12_:Point = null;
         var _loc13_:Point = null;
         var _loc14_:Point = null;
         var _loc4_:int = param1.n;
         if(param2 < 0)
         {
            _loc5_ = 0;
            _loc6_ = _loc4_ - 1;
            while(_loc5_ < _loc6_)
            {
               _loc14_ = param1.vertex[_loc5_];
               param1.vertex[_loc5_] = param1.vertex[_loc6_];
               param1.vertex[_loc6_] = _loc14_;
               _loc5_++;
               _loc6_--;
            }
         }
         _loc5_ = 0;
         while(_loc5_ < _loc4_)
         {
            _loc6_ = this.mod(_loc5_ + 1,_loc4_);
            _loc7_ = this.mod(_loc5_ + 2,_loc4_);
            _loc13_ = this.interval(1 / 2,param1.vertex[_loc7_],param1.vertex[_loc6_]);
            _loc9_ = this.ddenom(param1.vertex[_loc5_],param1.vertex[_loc7_]);
            if(_loc9_ != 0)
            {
               _loc8_ = this.dpara(param1.vertex[_loc5_],param1.vertex[_loc6_],param1.vertex[_loc7_]) / _loc9_;
               _loc8_ = Math.abs(_loc8_);
               _loc10_ = _loc8_ > 1?Number(1 - 1 / _loc8_):Number(0);
               _loc10_ = _loc10_ / 0.75;
            }
            else
            {
               _loc10_ = 4 / 3;
            }
            param1.alpha0[_loc6_] = _loc10_;
            if(_loc10_ > param3)
            {
               param1.tag[_loc6_] = POTRACE_CORNER;
               param1.controlPoints[_loc6_][1] = param1.vertex[_loc6_];
               param1.controlPoints[_loc6_][2] = _loc13_;
            }
            else
            {
               if(_loc10_ < 0.55)
               {
                  _loc10_ = 0.55;
               }
               else if(_loc10_ > 1)
               {
                  _loc10_ = 1;
               }
               _loc11_ = this.interval(0.5 + 0.5 * _loc10_,param1.vertex[_loc5_],param1.vertex[_loc6_]);
               _loc12_ = this.interval(0.5 + 0.5 * _loc10_,param1.vertex[_loc7_],param1.vertex[_loc6_]);
               param1.tag[_loc6_] = POTRACE_CURVETO;
               param1.controlPoints[_loc6_][0] = _loc11_;
               param1.controlPoints[_loc6_][1] = _loc12_;
               param1.controlPoints[_loc6_][2] = _loc13_;
            }
            param1.alpha[_loc6_] = _loc10_;
            param1.beta[_loc6_] = 0.5;
            _loc5_++;
         }
      }
      
      private function opticurve(param1:Path, param2:Number) : void
      {
         var _loc10_:int = 0;
         var _loc11_:int = 0;
         var _loc12_:Number = NaN;
         var _loc13_:Number = NaN;
         var _loc14_:Point = null;
         var _loc15_:int = 0;
         var _loc17_:Boolean = false;
         var _loc21_:int = 0;
         var _loc3_:int = param1.curves.n;
         var _loc4_:Vector.<int> = new Vector.<int>(_loc3_);
         var _loc5_:Vector.<Number> = new Vector.<Number>(_loc3_ + 1);
         var _loc6_:Vector.<int> = new Vector.<int>(_loc3_ + 1);
         var _loc7_:Vector.<Opti> = new Vector.<Opti>(_loc3_ + 1);
         var _loc8_:Vector.<int> = new Vector.<int>(_loc3_);
         var _loc9_:Vector.<Number> = new Vector.<Number>(_loc3_ + 1);
         var _loc16_:Opti = new Opti();
         _loc10_ = 0;
         while(_loc10_ < _loc3_)
         {
            if(param1.curves.tag[_loc10_] == POTRACE_CURVETO)
            {
               _loc8_[_loc10_] = this.sign(this.dpara(param1.curves.vertex[this.mod(_loc10_ - 1,_loc3_)],param1.curves.vertex[_loc10_],param1.curves.vertex[this.mod(_loc10_ + 1,_loc3_)]));
            }
            else
            {
               _loc8_[_loc10_] = 0;
            }
            _loc10_++;
         }
         _loc12_ = 0;
         _loc9_[0] = 0;
         _loc14_ = param1.curves.vertex[0];
         _loc10_ = 0;
         while(_loc10_ < _loc3_)
         {
            _loc15_ = this.mod(_loc10_ + 1,_loc3_);
            if(param1.curves.tag[_loc15_] == POTRACE_CURVETO)
            {
               _loc13_ = param1.curves.alpha[_loc15_];
               _loc12_ = _loc12_ + 0.3 * _loc13_ * (4 - _loc13_) * this.dpara(param1.curves.controlPoints[_loc10_][2],param1.curves.vertex[_loc15_],param1.curves.controlPoints[_loc15_][2]) / 2;
               _loc12_ = _loc12_ + this.dpara(_loc14_,param1.curves.controlPoints[_loc10_][2],param1.curves.controlPoints[_loc15_][2]) / 2;
            }
            _loc9_[_loc10_ + 1] = _loc12_;
            _loc10_++;
         }
         _loc4_[0] = -1;
         _loc5_[0] = 0;
         _loc6_[0] = 0;
         _loc11_ = 1;
         while(_loc11_ <= _loc3_)
         {
            _loc4_[_loc11_] = _loc11_ - 1;
            _loc5_[_loc11_] = _loc5_[_loc11_ - 1];
            _loc6_[_loc11_] = _loc6_[_loc11_ - 1] + 1;
            _loc10_ = _loc11_ - 2;
            while(_loc10_ >= 0)
            {
               _loc17_ = this.opti_penalty(param1,_loc10_,this.mod(_loc11_,_loc3_),_loc16_,param2,_loc8_,_loc9_);
               if(_loc17_)
               {
                  break;
               }
               if(_loc6_[_loc11_] > _loc6_[_loc10_] + 1 || _loc6_[_loc11_] == _loc6_[_loc10_] + 1 && _loc5_[_loc11_] > _loc5_[_loc10_] + _loc16_.pen)
               {
                  _loc4_[_loc11_] = _loc10_;
                  _loc5_[_loc11_] = _loc5_[_loc10_] + _loc16_.pen;
                  _loc6_[_loc11_] = _loc6_[_loc10_] + 1;
                  _loc7_[_loc11_] = _loc16_.clone();
               }
               _loc10_--;
            }
            _loc11_++;
         }
         var _loc18_:int = _loc6_[_loc3_];
         param1.optimizedCurves = new PrivCurve(_loc18_);
         var _loc19_:Vector.<Number> = new Vector.<Number>(_loc18_);
         var _loc20_:Vector.<Number> = new Vector.<Number>(_loc18_);
         _loc11_ = _loc3_;
         _loc10_ = _loc18_ - 1;
         while(_loc10_ >= 0)
         {
            _loc21_ = this.mod(_loc11_,_loc3_);
            if(_loc4_[_loc11_] == _loc11_ - 1)
            {
               param1.optimizedCurves.tag[_loc10_] = param1.curves.tag[_loc21_];
               param1.optimizedCurves.controlPoints[_loc10_][0] = param1.curves.controlPoints[_loc21_][0];
               param1.optimizedCurves.controlPoints[_loc10_][1] = param1.curves.controlPoints[_loc21_][1];
               param1.optimizedCurves.controlPoints[_loc10_][2] = param1.curves.controlPoints[_loc21_][2];
               param1.optimizedCurves.vertex[_loc10_] = param1.curves.vertex[_loc21_];
               param1.optimizedCurves.alpha[_loc10_] = param1.curves.alpha[_loc21_];
               param1.optimizedCurves.alpha0[_loc10_] = param1.curves.alpha0[_loc21_];
               param1.optimizedCurves.beta[_loc10_] = param1.curves.beta[_loc21_];
               _loc19_[_loc10_] = _loc20_[_loc10_] = 1;
            }
            else
            {
               param1.optimizedCurves.tag[_loc10_] = POTRACE_CURVETO;
               param1.optimizedCurves.controlPoints[_loc10_][0] = _loc7_[_loc11_].c[0];
               param1.optimizedCurves.controlPoints[_loc10_][1] = _loc7_[_loc11_].c[1];
               param1.optimizedCurves.controlPoints[_loc10_][2] = param1.curves.controlPoints[_loc21_][2];
               param1.optimizedCurves.vertex[_loc10_] = this.interval(_loc7_[_loc11_].s,param1.curves.controlPoints[_loc21_][2],param1.curves.vertex[_loc21_]);
               param1.optimizedCurves.alpha[_loc10_] = _loc7_[_loc11_].alpha;
               param1.optimizedCurves.alpha0[_loc10_] = _loc7_[_loc11_].alpha;
               _loc19_[_loc10_] = _loc7_[_loc11_].s;
               _loc20_[_loc10_] = _loc7_[_loc11_].t;
            }
            _loc11_ = _loc4_[_loc11_];
            _loc10_--;
         }
         _loc10_ = 0;
         while(_loc10_ < _loc18_)
         {
            _loc15_ = this.mod(_loc10_ + 1,_loc18_);
            param1.optimizedCurves.beta[_loc10_] = _loc19_[_loc10_] / (_loc19_[_loc10_] + _loc20_[_loc15_]);
            _loc10_++;
         }
      }
      
      private function opti_penalty(param1:Path, param2:int, param3:int, param4:Opti, param5:Number, param6:Vector.<int>, param7:Vector.<Number>) : Boolean
      {
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         var _loc11_:int = 0;
         var _loc12_:int = 0;
         var _loc13_:int = 0;
         var _loc14_:Number = NaN;
         var _loc15_:Number = NaN;
         var _loc16_:Number = NaN;
         var _loc17_:Number = NaN;
         var _loc18_:Point = null;
         var _loc8_:int = param1.curves.n;
         if(param2 == param3)
         {
            return true;
         }
         _loc9_ = param2;
         _loc13_ = this.mod(param2 + 1,_loc8_);
         _loc10_ = this.mod(_loc9_ + 1,_loc8_);
         _loc12_ = param6[_loc10_];
         if(_loc12_ == 0)
         {
            return true;
         }
         _loc15_ = this.ddist(param1.curves.vertex[param2],param1.curves.vertex[_loc13_]);
         _loc9_ = _loc10_;
         while(_loc9_ != param3)
         {
            _loc10_ = this.mod(_loc9_ + 1,_loc8_);
            _loc11_ = this.mod(_loc9_ + 2,_loc8_);
            if(param6[_loc10_] != _loc12_)
            {
               return true;
            }
            if(this.sign(this.cprod(param1.curves.vertex[param2],param1.curves.vertex[_loc13_],param1.curves.vertex[_loc10_],param1.curves.vertex[_loc11_])) != _loc12_)
            {
               return true;
            }
            if(this.iprod1(param1.curves.vertex[param2],param1.curves.vertex[_loc13_],param1.curves.vertex[_loc10_],param1.curves.vertex[_loc11_]) < _loc15_ * this.ddist(param1.curves.vertex[_loc10_],param1.curves.vertex[_loc11_]) * COS179)
            {
               return true;
            }
            _loc9_ = _loc10_;
         }
         var _loc19_:Point = param1.curves.controlPoints[this.mod(param2,_loc8_)][2];
         var _loc20_:Point = param1.curves.vertex[this.mod(param2 + 1,_loc8_)];
         var _loc21_:Point = param1.curves.vertex[this.mod(param3,_loc8_)];
         var _loc22_:Point = param1.curves.controlPoints[this.mod(param3,_loc8_)][2];
         _loc14_ = param7[param3] - param7[param2];
         _loc14_ = _loc14_ - this.dpara(param1.curves.vertex[0],param1.curves.controlPoints[param2][2],param1.curves.controlPoints[param3][2]) / 2;
         if(param2 >= param3)
         {
            _loc14_ = _loc14_ + param7[_loc8_];
         }
         var _loc23_:Number = this.dpara(_loc19_,_loc20_,_loc21_);
         var _loc24_:Number = this.dpara(_loc19_,_loc20_,_loc22_);
         var _loc25_:Number = this.dpara(_loc19_,_loc21_,_loc22_);
         var _loc26_:Number = _loc23_ + _loc25_ - _loc24_;
         if(_loc24_ == _loc23_)
         {
            return true;
         }
         var _loc27_:Number = _loc25_ / (_loc25_ - _loc26_);
         var _loc28_:Number = _loc24_ / (_loc24_ - _loc23_);
         var _loc29_:Number = _loc24_ * _loc27_ / 2;
         if(_loc29_ == 0)
         {
            return true;
         }
         var _loc30_:Number = _loc14_ / _loc29_;
         var _loc31_:Number = 2 - Math.sqrt(4 - _loc30_ / 0.3);
         param4.c = new Vector.<Point>(2);
         param4.c[0] = this.interval(_loc27_ * _loc31_,_loc19_,_loc20_);
         param4.c[1] = this.interval(_loc28_ * _loc31_,_loc22_,_loc21_);
         param4.alpha = _loc31_;
         param4.t = _loc27_;
         param4.s = _loc28_;
         _loc20_ = param4.c[0];
         _loc21_ = param4.c[1];
         param4.pen = 0;
         _loc9_ = this.mod(param2 + 1,_loc8_);
         while(_loc9_ != param3)
         {
            _loc10_ = this.mod(_loc9_ + 1,_loc8_);
            _loc27_ = this.tangent(_loc19_,_loc20_,_loc21_,_loc22_,param1.curves.vertex[_loc9_],param1.curves.vertex[_loc10_]);
            if(_loc27_ < -0.5)
            {
               return true;
            }
            _loc18_ = this.bezier(_loc27_,_loc19_,_loc20_,_loc21_,_loc22_);
            _loc15_ = this.ddist(param1.curves.vertex[_loc9_],param1.curves.vertex[_loc10_]);
            if(_loc15_ == 0)
            {
               return true;
            }
            _loc16_ = this.dpara(param1.curves.vertex[_loc9_],param1.curves.vertex[_loc10_],_loc18_) / _loc15_;
            if(Math.abs(_loc16_) > param5)
            {
               return true;
            }
            if(this.iprod(param1.curves.vertex[_loc9_],param1.curves.vertex[_loc10_],_loc18_) < 0 || this.iprod(param1.curves.vertex[_loc10_],param1.curves.vertex[_loc9_],_loc18_) < 0)
            {
               return true;
            }
            param4.pen = param4.pen + _loc16_ * _loc16_;
            _loc9_ = _loc10_;
         }
         _loc9_ = param2;
         while(_loc9_ != param3)
         {
            _loc10_ = this.mod(_loc9_ + 1,_loc8_);
            _loc27_ = this.tangent(_loc19_,_loc20_,_loc21_,_loc22_,param1.curves.controlPoints[_loc9_][2],param1.curves.controlPoints[_loc10_][2]);
            if(_loc27_ < -0.5)
            {
               return true;
            }
            _loc18_ = this.bezier(_loc27_,_loc19_,_loc20_,_loc21_,_loc22_);
            _loc15_ = this.ddist(param1.curves.controlPoints[_loc9_][2],param1.curves.controlPoints[_loc10_][2]);
            if(_loc15_ == 0)
            {
               return true;
            }
            _loc16_ = this.dpara(param1.curves.controlPoints[_loc9_][2],param1.curves.controlPoints[_loc10_][2],_loc18_) / _loc15_;
            _loc17_ = this.dpara(param1.curves.controlPoints[_loc9_][2],param1.curves.controlPoints[_loc10_][2],param1.curves.vertex[_loc10_]) / _loc15_;
            _loc17_ = _loc17_ * (0.75 * param1.curves.alpha[_loc10_]);
            if(_loc17_ < 0)
            {
               _loc16_ = -_loc16_;
               _loc17_ = -_loc17_;
            }
            if(_loc16_ < _loc17_ - param5)
            {
               return true;
            }
            if(_loc16_ < _loc17_)
            {
               param4.pen = param4.pen + (_loc16_ - _loc17_) * (_loc16_ - _loc17_);
            }
            _loc9_ = _loc10_;
         }
         return false;
      }
      
      private function pathlist_to_curvearrayslist(param1:Array) : Array
      {
         var _loc4_:Array = null;
         var _loc5_:Array = null;
         var _loc6_:int = 0;
         var _loc7_:Path = null;
         var _loc8_:Point = null;
         var _loc9_:Array = null;
         var _loc10_:int = 0;
         var _loc11_:Point = null;
         var _loc12_:Point = null;
         var _loc13_:Point = null;
         var _loc14_:Curve = null;
         var _loc15_:Curve = null;
         var _loc16_:Array = null;
         var _loc17_:int = 0;
         var _loc2_:Array = [];
         var _loc3_:int = 0;
         while(_loc3_ < param1.length)
         {
            _loc4_ = param1[_loc3_] as Array;
            _loc5_ = [];
            _loc2_.push(_loc5_);
            _loc6_ = 0;
            while(_loc6_ < _loc4_.length)
            {
               _loc7_ = _loc4_[_loc6_] as Path;
               _loc8_ = _loc7_.curves.controlPoints[_loc7_.curves.n - 1][2];
               _loc9_ = [];
               _loc10_ = 0;
               while(_loc10_ < _loc7_.curves.n)
               {
                  _loc11_ = _loc7_.curves.controlPoints[_loc10_][0];
                  _loc12_ = _loc7_.curves.controlPoints[_loc10_][1];
                  _loc13_ = _loc7_.curves.controlPoints[_loc10_][2];
                  if(_loc7_.curves.tag[_loc10_] == POTRACE_CORNER)
                  {
                     this.add_curve(_loc9_,_loc8_,_loc8_,_loc12_,_loc12_);
                     this.add_curve(_loc9_,_loc12_,_loc12_,_loc13_,_loc13_);
                  }
                  else
                  {
                     this.add_curve(_loc9_,_loc8_,_loc11_,_loc12_,_loc13_);
                  }
                  _loc8_ = _loc13_;
                  _loc10_++;
               }
               if(_loc9_.length > 0)
               {
                  _loc14_ = _loc9_[_loc9_.length - 1] as Curve;
                  _loc15_ = _loc9_[0] as Curve;
                  if(_loc14_.kind == CurveKind.LINE && _loc15_.kind == CurveKind.LINE && this.iprod(_loc14_.b,_loc14_.a,_loc15_.b) < 0 && Math.abs(this.xprodf(new Point(_loc15_.b.x - _loc15_.a.x,_loc15_.b.y - _loc15_.a.y),new Point(_loc14_.a.x - _loc14_.a.x,_loc14_.b.y - _loc14_.a.y))) < 0.01)
                  {
                     _loc9_[0] = new Curve(CurveKind.LINE,_loc14_.a,_loc14_.a,_loc14_.a,_loc15_.b);
                     _loc9_.pop();
                  }
                  _loc16_ = [];
                  _loc17_ = 0;
                  while(_loc17_ < _loc9_.length)
                  {
                     _loc16_.push(_loc9_[_loc17_]);
                     _loc17_++;
                  }
                  _loc5_.push(_loc16_);
               }
               _loc6_++;
            }
            _loc3_++;
         }
         return _loc2_;
      }
      
      private function add_curve(param1:Array, param2:Point, param3:Point, param4:Point, param5:Point) : void
      {
         var _loc6_:int = 0;
         var _loc7_:Curve = null;
         if(Math.abs(this.xprodf(new Point(param3.x - param2.x,param3.y - param2.y),new Point(param5.x - param2.x,param5.y - param2.y))) < 0.01 && Math.abs(this.xprodf(new Point(param4.x - param5.x,param4.y - param5.y),new Point(param5.x - param2.x,param5.y - param2.y))) < 0.01)
         {
            _loc6_ = CurveKind.LINE;
         }
         else
         {
            _loc6_ = CurveKind.BEZIER;
         }
         if(_loc6_ == CurveKind.LINE)
         {
            if(param1.length > 0 && Curve(param1[param1.length - 1]).kind == CurveKind.LINE)
            {
               _loc7_ = param1[param1.length - 1] as Curve;
               if(Math.abs(this.xprodf(new Point(_loc7_.b.x - _loc7_.a.x,_loc7_.b.y - _loc7_.a.y),new Point(param5.x - param2.x,param5.y - param2.y))) < 0.01 && this.iprod(_loc7_.b,_loc7_.a,param5) < 0)
               {
                  param1[param1.length - 1] = new Curve(_loc6_,_loc7_.a,_loc7_.a,_loc7_.a,param5);
               }
               else
               {
                  param1.push(new Curve(CurveKind.LINE,param2,param3,param4,param5));
               }
            }
            else
            {
               param1.push(new Curve(CurveKind.LINE,param2,param3,param4,param5));
            }
         }
         else
         {
            param1.push(new Curve(CurveKind.BEZIER,param2,param3,param4,param5));
         }
      }
      
      private function dorth_infty(param1:Point, param2:Point) : PointInt
      {
         return new PointInt(-this.sign(param2.y - param1.y),this.sign(param2.x - param1.x));
      }
      
      private function dpara(param1:Point, param2:Point, param3:Point) : Number
      {
         return (param2.x - param1.x) * (param3.y - param1.y) - (param3.x - param1.x) * (param2.y - param1.y);
      }
      
      private function ddenom(param1:Point, param2:Point) : Number
      {
         var _loc3_:PointInt = this.dorth_infty(param1,param2);
         return _loc3_.y * (param2.x - param1.x) - _loc3_.x * (param2.y - param1.y);
      }
      
      private function cyclic(param1:int, param2:int, param3:int) : Boolean
      {
         if(param1 <= param3)
         {
            return param1 <= param2 && param2 < param3;
         }
         return param1 <= param2 || param2 < param3;
      }
      
      private function pointslope(param1:Path, param2:int, param3:int, param4:Point, param5:Point) : void
      {
         var _loc8_:Number = NaN;
         var _loc6_:int = param1.pt.length;
         var _loc7_:Vector.<SumStruct> = param1.sums;
         var _loc9_:int = 0;
         while(param3 >= _loc6_)
         {
            param3 = param3 - _loc6_;
            _loc9_++;
         }
         while(param2 >= _loc6_)
         {
            param2 = param2 - _loc6_;
            _loc9_--;
         }
         while(param3 < 0)
         {
            param3 = param3 + _loc6_;
            _loc9_--;
         }
         while(param2 < 0)
         {
            param2 = param2 + _loc6_;
            _loc9_++;
         }
         var _loc10_:Number = _loc7_[param3 + 1].x - _loc7_[param2].x + _loc9_ * _loc7_[_loc6_].x;
         var _loc11_:Number = _loc7_[param3 + 1].y - _loc7_[param2].y + _loc9_ * _loc7_[_loc6_].y;
         var _loc12_:Number = _loc7_[param3 + 1].x2 - _loc7_[param2].x2 + _loc9_ * _loc7_[_loc6_].x2;
         var _loc13_:Number = _loc7_[param3 + 1].xy - _loc7_[param2].xy + _loc9_ * _loc7_[_loc6_].xy;
         var _loc14_:Number = _loc7_[param3 + 1].y2 - _loc7_[param2].y2 + _loc9_ * _loc7_[_loc6_].y2;
         var _loc15_:Number = param3 + 1 - param2 + _loc9_ * _loc6_;
         param4.x = _loc10_ / _loc15_;
         param4.y = _loc11_ / _loc15_;
         var _loc16_:Number = (_loc12_ - _loc10_ * _loc10_ / _loc15_) / _loc15_;
         var _loc17_:Number = (_loc13_ - _loc10_ * _loc11_ / _loc15_) / _loc15_;
         var _loc18_:Number = (_loc14_ - _loc11_ * _loc11_ / _loc15_) / _loc15_;
         var _loc19_:Number = (_loc16_ + _loc18_ + Math.sqrt((_loc16_ - _loc18_) * (_loc16_ - _loc18_) + 4 * _loc17_ * _loc17_)) / 2;
         _loc16_ = _loc16_ - _loc19_;
         _loc18_ = _loc18_ - _loc19_;
         if(Math.abs(_loc16_) >= Math.abs(_loc18_))
         {
            _loc8_ = Math.sqrt(_loc16_ * _loc16_ + _loc17_ * _loc17_);
            if(_loc8_ != 0)
            {
               param5.x = -_loc17_ / _loc8_;
               param5.y = _loc16_ / _loc8_;
            }
         }
         else
         {
            _loc8_ = Math.sqrt(_loc18_ * _loc18_ + _loc17_ * _loc17_);
            if(_loc8_ != 0)
            {
               param5.x = -_loc18_ / _loc8_;
               param5.y = _loc17_ / _loc8_;
            }
         }
         if(_loc8_ == 0)
         {
            param5.x = param5.y = 0;
         }
      }
      
      private function quadform(param1:Vector.<Vector.<Number>>, param2:Point) : Number
      {
         var _loc6_:int = 0;
         var _loc3_:Number = 0;
         var _loc4_:Vector.<Number> = new Vector.<Number>(3);
         _loc4_[0] = param2.x;
         _loc4_[1] = param2.y;
         _loc4_[2] = 1;
         var _loc5_:int = 0;
         while(_loc5_ < 3)
         {
            _loc6_ = 0;
            while(_loc6_ < 3)
            {
               _loc3_ = _loc3_ + _loc4_[_loc5_] * param1[_loc5_][_loc6_] * _loc4_[_loc6_];
               _loc6_++;
            }
            _loc5_++;
         }
         return _loc3_;
      }
      
      private function bezier(param1:Number, param2:Point, param3:Point, param4:Point, param5:Point) : Point
      {
         var _loc6_:Number = 1 - param1;
         var _loc7_:Point = new Point();
         _loc7_.x = _loc6_ * _loc6_ * _loc6_ * param2.x + 3 * (_loc6_ * _loc6_ * param1) * param3.x + 3 * (param1 * param1 * _loc6_) * param4.x + param1 * param1 * param1 * param5.x;
         _loc7_.y = _loc6_ * _loc6_ * _loc6_ * param2.y + 3 * (_loc6_ * _loc6_ * param1) * param3.y + 3 * (param1 * param1 * _loc6_) * param4.y + param1 * param1 * param1 * param5.y;
         return _loc7_;
      }
      
      private function tangent(param1:Point, param2:Point, param3:Point, param4:Point, param5:Point, param6:Point) : Number
      {
         var _loc7_:Number = this.cprod(param1,param2,param5,param6);
         var _loc8_:Number = this.cprod(param2,param3,param5,param6);
         var _loc9_:Number = this.cprod(param3,param4,param5,param6);
         var _loc10_:Number = _loc7_ - 2 * _loc8_ + _loc9_;
         var _loc11_:Number = -2 * _loc7_ + 2 * _loc8_;
         var _loc12_:Number = _loc7_;
         var _loc13_:Number = _loc11_ * _loc11_ - 4 * _loc10_ * _loc12_;
         if(_loc10_ == 0 || _loc13_ < 0)
         {
            return -1;
         }
         var _loc14_:Number = Math.sqrt(_loc13_);
         var _loc15_:Number = (-_loc11_ + _loc14_) / (2 * _loc10_);
         var _loc16_:Number = (-_loc11_ - _loc14_) / (2 * _loc10_);
         if(_loc15_ >= 0 && _loc15_ <= 1)
         {
            return _loc15_;
         }
         if(_loc16_ >= 0 && _loc16_ <= 1)
         {
            return _loc16_;
         }
         return -1;
      }
      
      private function ddist(param1:Point, param2:Point) : Number
      {
         return Math.sqrt((param1.x - param2.x) * (param1.x - param2.x) + (param1.y - param2.y) * (param1.y - param2.y));
      }
      
      private function xprod(param1:PointInt, param2:PointInt) : int
      {
         return param1.x * param2.y - param1.y * param2.x;
      }
      
      private function xprodf(param1:Point, param2:Point) : int
      {
         return param1.x * param2.y - param1.y * param2.x;
      }
      
      private function cprod(param1:Point, param2:Point, param3:Point, param4:Point) : Number
      {
         return (param2.x - param1.x) * (param4.y - param3.y) - (param4.x - param3.x) * (param2.y - param1.y);
      }
      
      private function iprod(param1:Point, param2:Point, param3:Point) : Number
      {
         return (param2.x - param1.x) * (param3.x - param1.x) + (param2.y - param1.y) * (param3.y - param1.y);
      }
      
      private function iprod1(param1:Point, param2:Point, param3:Point, param4:Point) : Number
      {
         return (param2.x - param1.x) * (param4.x - param3.x) + (param2.y - param1.y) * (param4.y - param3.y);
      }
      
      private function interval(param1:Number, param2:Point, param3:Point) : Point
      {
         return new Point(param2.x + param1 * (param3.x - param2.x),param2.y + param1 * (param3.y - param2.y));
      }
      
      private function abs(param1:int) : int
      {
         return param1 > 0?int(param1):int(-param1);
      }
      
      private function floordiv(param1:int, param2:int) : int
      {
         return param1 >= 0?int(param1 / param2):int(-1 - (-1 - param1) / param2);
      }
      
      private function min(param1:int, param2:int) : int
      {
         return param1 < param2?int(param1):int(param2);
      }
      
      private function mod(param1:int, param2:int) : int
      {
         return param1 >= param2?int(param1 % param2):param1 >= 0?int(param1):int(param2 - 1 - (-1 - param1) % param2);
      }
      
      private function sign(param1:int) : int
      {
         return param1 > 0?1:param1 < 0?-1:0;
      }
   }
}
